package com.xinchuang.utils;


import com.alibaba.fastjson.JSONArray;
import org.gdal.gdal.Dataset;
import org.gdal.gdal.gdal;
import org.gdal.gdalconst.gdalconstConstants;

import java.awt.*;
import java.awt.geom.Arc2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.io.IOException;

/**
 * TODO
 *
 * @author zkwczx
 * @version 1.0
 * @date 2024/7/3 14:14
 */
public class DrawOnTiff {

    static {
        gdal.AllRegister();
    }

    public static void main(String[] args) throws IOException {
//        // 读取TIF图像
//        BufferedImage tifImage = ImageIO.read(new File("D:\\data\\那霸机场.tif"));
////
////        // 创建Graphics2D对象
//        Graphics2D g2d = tifImage.createGraphics();
////
////        // 绘制一个简单的图形，比如一个矩形
////        g2d.drawRect(2077, 1811, 2, 2);
//
////        g2d.drawRect(2130, 1868, 2, 2);
//
//        // 设置绘制的颜色
////        g2d.setColor(Color.BLUE);
//
//        // 定义多边形的顶点坐标
//        int[] xPoints = {2077,1811, 2130,1811};
//        int[] yPoints = {2077,1868, 2130,1868};
////        int nPoints = xPoints.length;
//
//        // 创建Polygon对象
////        Polygon polygon = new Polygon(xPoints, yPoints, nPoints);
//
//        // 创建一个GeneralPath对象
//        GeneralPath path = new GeneralPath();
//
//        // 移动到第一个点
//        path.moveTo(2077, 1811);
//        // 添加其他顶点
//        path.lineTo(2130, 1811);
//        path.lineTo(2130, 1868);
//        path.lineTo(2077, 1868);
//
//        // 关闭路径，形成多边形
//        path.closePath();
//
//        // 绘制多边形轮廓
//        g2d.draw(path);
//
//        // 释放图形上下文使用的资源
//        g2d.dispose();
//
//        // 将修改后的图像保存为新的TIF图像
//        ImageIO.write(tifImage, "TIFF", new File("D:\\data\\output.tif"));

        DrawOnTiff tiff = new DrawOnTiff();
        Dataset dataset = tiff.openFile("D:\\data\\newTarget\\tif\\那霸机场.tif");
        int[] ints = tiff.geoToPixel(dataset, 127.64828250234132, 26.19334235929273);
        System.out.println(ints[0]);
        System.out.println(ints[1]);
    }

    /**
     * 打开tif图
     * @param filePath
     * @return
     */
    public Dataset openFile(String filePath) {
        // 打开GeoTIFF文件
        Dataset dataset = gdal.Open(filePath, gdalconstConstants.GA_ReadOnly);
        if (dataset == null) {
            System.out.println("Could not open file");
            return null;
        }
        return dataset;
    }

    /**
     * 在图上画一个多边形
     * @param dataset
     * @param g2d
     * @param array
     */
    public void toPosition(Dataset dataset, Graphics2D g2d, JSONArray array) {
        // 创建一个GeneralPath对象
        GeneralPath path = new GeneralPath();
        for (int i = 0; i < array.size(); i++) {
            JSONArray jsonArray = array.getJSONArray(i);
            int[] ints = geoToPixel(dataset, jsonArray.getDouble(0), jsonArray.getDouble(1));
            if (i == 0) {
                // 移动到第一个点
                path.moveTo(ints[0], ints[1]);
            } else {
                // 添加其他顶点
                path.lineTo(ints[0], ints[1]);
            }
        }
        // 关闭路径，形成多边形
        path.closePath();
        g2d.setColor(Color.WHITE);
        // 绘制多边形轮廓
        g2d.draw(path);
    }

    /**
     *
     * @param dataset
     * @param g2d
     * @param array
     */
    public void toClosePosition(Dataset dataset, Graphics2D g2d, JSONArray array) {
        // 创建一个GeneralPath对象
        GeneralPath path = new GeneralPath();
        for (int i = 0; i < array.size(); i++) {
            JSONArray jsonArray = array.getJSONArray(i);
            int[] ints = geoToPixel(dataset, jsonArray.getDouble(0), jsonArray.getDouble(1));
            if (i == 0) {
                // 移动到第一个点
                path.moveTo(ints[0], ints[1]);
            } else {
                // 添加其他顶点
                path.lineTo(ints[0], ints[1]);
            }
        }
        // 关闭路径，形成多边形
        path.closePath();
        // 绘制多边形轮廓
        g2d.setColor(Color.LIGHT_GRAY);
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
        g2d.fill(path);
        g2d.setColor(Color.WHITE);
        g2d.draw(path);
    }

    /**
     * 在图上画一个线段
     * @param dataset
     * @param g2d
     * @param array
     */
    public void toLine(Dataset dataset, Graphics2D g2d, JSONArray array) {
        // 创建一个GeneralPath对象
        GeneralPath path = new GeneralPath();
        for (int i = 0; i < array.size(); i++) {
            JSONArray jsonArray = array.getJSONArray(i);
            int[] ints = geoToPixel(dataset, jsonArray.getDouble(0), jsonArray.getDouble(1));
            if (i == 0) {
                // 移动到第一个点
                path.moveTo(ints[0], ints[1]);
            } else {
                // 添加其他顶点
                path.lineTo(ints[0], ints[1]);
            }
        }
        // 绘制轮廓
        BasicStroke basicStroke = new BasicStroke(3);
        g2d.setStroke(basicStroke);
        g2d.setColor(Color.WHITE);
        g2d.draw(path);
    }

    /**
     * 在图上的一个点标注一段文字
     * @param dataset
     * @param g2d
     * @param lng
     * @param lat
     * @param message
     */
    public void toText(Dataset dataset, Graphics2D g2d, double lng, double lat, String message) {
        // 设置字体和颜色
        Font font = new Font("Serif", Font.PLAIN, 12);
        g2d.setFont(font);
        g2d.setColor(Color.WHITE);
        int[] ints = geoToPixel(dataset, lng, lat);
        g2d.drawString(message, ints[0], ints[1]);
    }

    /**
     * 在图上的一个点标注一段文字
     * @param dataset
     * @param g2d
     * @param lng
     * @param lat
     * @param message
     */
    public void toText(Dataset dataset, Graphics2D g2d, double lng, double lat, String message, int size) {
        // 设置字体和颜色
        Font font = new Font("sans-serif", Font.BOLD, size);
        g2d.setFont(font);
        g2d.setColor(Color.WHITE);
        int[] ints = geoToPixel(dataset, lng, lat);
        g2d.drawString(message, ints[0], ints[1]);
    }

    /**
     * 画一个点
     * @param dataset
     * @param g2d
     * @param lng
     * @param lat
     * @param width
     */
    public void paintComponent(Dataset dataset, Graphics2D g2d, double lng, double lat, int width) {
        int[] ints = geoToPixel(dataset, lng, lat);
        // 设置颜色并绘制蓝色圆
        g2d.setColor(Color.LIGHT_GRAY);
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
        g2d.fillOval(ints[0], ints[1], width * 2, width * 2);
    }

    public void geoToPixel(double geoX, double geoY, double[] ori_transform, double[] pixelXY) {
        final int maxIterations = 1000;
        final double tolerance = 0.1;
        double pixelX = 0, pixelY = 0;

        for (int i = 0; i < maxIterations; i++) {
            // 先假设当前的pixelX和pixelY是正确的
            double newX = ori_transform[0] + pixelX * ori_transform[1] + pixelY * ori_transform[2];
            double newY = ori_transform[3] + pixelX * ori_transform[4] + pixelY * ori_transform[5];

            // 更新pixelX和pixelY
            pixelX = (geoX - ori_transform[0] - pixelY * ori_transform[2]) / ori_transform[1];
            pixelY = (geoY - ori_transform[3] - pixelX * ori_transform[4]) / ori_transform[5];

            // 如果新旧坐标相差小于某个阈值，则认为已经收敛
            if (Math.abs(geoX - newX) < tolerance && Math.abs(geoY - newY) < tolerance) {
                break;
            }
        }

        pixelXY[0] = pixelX;
        pixelXY[1] = pixelY;
    }

    public int[] geoToPixel(Dataset dataset, double longitude, double latitude) {
//        Dataset dataset = gdal.Open(tifUrl, gdalconstConstants.GA_ReadOnly);
//        double[] ori_transform = dataset.GetGeoTransform();
//
//        double[] pixelXY = new double[2];
//        geoToPixel(lng, lat, ori_transform, pixelXY);
//
//        System.out.println("地理坐标 (" + lng + ", " + lat + ") 对应的像素坐标为 (" + pixelXY[0] + ", " + pixelXY[1] + ")");
//        System.out.println(pixelXY[0]);
//        System.out.println(pixelXY[1]);
        try {
            // 获取GeoTransform矩阵
            double[] geoTransform = new double[6];
            dataset.GetGeoTransform(geoTransform);

            // 使用逆GeoTransform计算像素坐标
            double pixel = geoTransform[1] * longitude + geoTransform[2] * latitude + geoTransform[0];
            double line = geoTransform[4] * longitude + geoTransform[5] * latitude + geoTransform[3];

            // 计算像素位置
            int pixelPos = (int) Math.round((longitude - geoTransform[0]) / geoTransform[1]);
            int linePos = (int) Math.round((latitude - geoTransform[3]) / geoTransform[5]);

            int[] pos = new int[2];
            pos[0] = pixelPos;
            pos[1] = linePos;
            // 输出像素位置
            System.out.println("Pixel coordinates: (" + pixelPos + ", " + linePos + ")");
            return pos;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

}
